# Popover Private

## Installation
`npm i @snack-uikit/popover-private`

[Changelog](./CHANGELOG.md)

## Example

```typescript jsx
import { PopoverPrivate } from "@snack-uikit/popover-private";

function App() {
  return (
    <PopoverPrivate
        placement='top'
        popoverContent='Не нажимать, опасно!'
        trigger='click'
      >
        <button>Button with popover</button>
    </PopoverPrivate>
  );
}
```

[//]: DOCUMENTATION_SECTION_START
[//]: THIS_SECTION_IS_AUTOGENERATED_PLEASE_DONT_EDIT_IT
## PopoverPrivate
### Props
| name | type | default value | description |
|------|------|---------------|-------------|
| trigger* | enum Trigger: `"click"`, `"hover"`, `"focusVisible"`, `"focus"`, `"hoverAndFocusVisible"`, `"hoverAndFocus"`, `"clickAndFocusVisible"` | - | Условие отображения поповера: <br> - `click` - открывать по клику <br> - `hover` - открывать по ховеру <br> - `focusVisible` - открывать по focus-visible <br> - `focus` - открывать по фокусу <br> - `hoverAndFocusVisible` - открывать по ховеру и focus-visible <br> - `hoverAndFocus` - открывать по ховеру и фокусу <br> - `clickAndFocusVisible` - открывать по клику и focus-visible |
| popoverContent* | `ReactNode \| ReactNode[]` | - | Контент поповера |
| children* | `ReactNode \| ChildrenFunction` | - | Триггер поповера (подробнее читайте ниже) |
| placement* | enum Placement: `"left"`, `"left-start"`, `"left-end"`, `"right"`, `"right-start"`, `"right-end"`, `"top"`, `"top-start"`, `"top-end"`, `"bottom"`, `"bottom-start"`, `"bottom-end"` | top | Положение поповера относительно своего триггера (children). |
| open | `boolean` | - | Управляет состоянием показан/не показан. |
| onOpenChange | `(isOpen: boolean) => void` | - | Колбек отображения компонента. Срабатывает при изменении состояния open. |
| outsideClick | `boolean \| OutsideClickHandler` | - | Закрывать ли при клике вне поповера |
| className | `string` | - | CSS-класс |
| triggerClassName | `string` | - | CSS-класс триггера |
| hasArrow | `boolean` | - | Параметр наличия стрелки у поповера. В размеры стрелки встроен отступ. Дополнительный отступ может быть задан параметром `offset`. У элемента стрелки нет цвета, необходимо задавать его через параметр `arrowClassName`. |
| arrowContainerClassName | `string` | - | CSS-класс контейнера стрелки поповера |
| arrowElementClassName | `string` | - | CSS-класс стрелки поповера |
| offset | `number` | 0 | Отступ поповера от его триггер-элемента (в пикселях). |
| hoverDelayOpen | `number` | - | Задержка открытия по ховеру |
| hoverDelayClose | `number` | - | Задержка закрытия по ховеру |
| triggerRef | `ForwardedRef<ReferenceType \| HTMLElement>` | - | Ref ссылка на триггер |
| widthStrategy | enum PopoverWidthStrategy: `"auto"`, `"gte"`, `"eq"` | auto | Стратегия управления шириной контейнера поповера <br> - `auto` - соответствует ширине контента, <br> - `gte` - Great Than or Equal, равен ширине таргета или больше ее, если контент в поповере шире, <br> - `eq` - Equal, строго равен ширине таргета. |
| heightStrategy | enum PopoverHeightStrategy: `"auto"`, `"eq"`, `"lte"` | auto | Стратегия управления высотой контейнера поповера <br> - `auto` - соответствует высоте контента, <br> - `lte` - Less Than or Equal, равен высоте таргета или меньше ее, если контент в поповере меньше, <br> - `eq` - Equal, строго равен высоте таргета. |
| closeOnEscapeKey | `boolean` | true | Закрывать ли по нажатию на кнопку `Esc` |
| triggerClickByKeys | `boolean` | true | Вызывается ли попоповер по нажатию клавиш Enter/Space (при trigger = `click`) |
| fallbackPlacements | `Placement[]` | - | Цепочка расположений которая будет применяться к поповеру от первого к последнему если при текущем он не влезает. |
| disableSpanWrapper | `boolean` | - | Отключает для `isValidElement` внешнюю обертку триггера <br> Пригодится для элементов с `position: absolute` |


[//]: DOCUMENTATION_SECTION_END


#### **`children: ReactNode | ChildrenFunction`**
  Референс, относительно которого рисуется поповер. Возможно несколько вариантов:
 - в **`children`** передан компонент, который принимает в себя `ref`. В таком случае пропсы этого компонента будут дополнены необходимыми для работы триггеров отображения: `useHoverTrigger`, `useClickTrigger`, `useFocusTrigger`. 
    
    > Осторожно, `ref` будет перезаписан. Если вы хотите получить ref на children поповера, можете передать ref в параметр triggerRef. Тогда поповер установит туда значение:
    ```typescript jsx
      <PopoverPrivate
        popoverContent={<div className={style.content}>some tip here</div>}
        useHoverTrigger
        triggerRef={(button) => { /* button HTMLElement из children */ }}
      >
        <button>some button</button>
      </PopoverPrivate>
    ```

  - в **`children`** передан компонент, который **НЕ** принимает в себя `ref`. В таком случае компонент будет обернут в `span`, который и послужит рефом для поповера.

  - в **`children`** передана функция. Эта функция будет вызвана на каждый рендер, она должна возвращать `ReactNode`. В параметры принимает ref, который нужно установить в целевой компонент и функцию `getReferenceProps`, возвращающую необходимые для ref параметры.
  Пример:
    ```typescript jsx
      <PopoverPrivate
        popoverContent={<div className={style.content}>some tip here</div>}
        useHoverTrigger
      >
        {({ getReferenceProps, ref }) => (
          <label>
            Set the value
            <input ref={ref} {...getReferenceProps({ onClick: onClickInputHandler })} />
          </label>
        )}
      </PopoverPrivate>
    ```

  - в **`children`** передан примитив string, number или React.Fragment. Children будет обернут в `span`.
